package com.xyh.transaction.utils;

import com.lowagie.text.pdf.BaseFont;
import com.xyh.transaction.entity.dto.goods.GoodsInvoice;
import com.xyh.transaction.entity.dto.goods.GoodsInvoiceItem;
import com.xyh.transaction.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.dromara.pdf.fop.handler.TemplateHandler;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
public class PdfUtil {


    public static byte[] generateInvoicePdf(String buyerName, String invoiceNumber,
                                            String buyerEmail, String buyerAddress, String sellerName,
                                            String sellerContact, List<GoodsInvoice> goodsItems, String totalAmount, String taxAmount,
                                            String discountAmount, String finalAmount, String paymentMethod,
                                            String orderNumber) {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("/pdf/");
        templateResolver.setTemplateMode("HTML");
        templateResolver.setSuffix(".html");
        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);

        // 1. 使用 Thymeleaf 渲染 HTML
        Context context = new Context();
        context.setVariable("buyerName", buyerName);
        context.setVariable("invoiceNumber", invoiceNumber);
        context.setVariable("buyerEmail", buyerEmail);
        context.setVariable("buyerAddress", buyerAddress);
        context.setVariable("invoiceDate", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        context.setVariable("sellerName", sellerName);
        context.setVariable("sellerContact", sellerContact);
        context.setVariable("goodsItems", goodsItems);
        context.setVariable("totalAmount", totalAmount);
        context.setVariable("taxAmount", taxAmount);
        context.setVariable("discountAmount", discountAmount);
        context.setVariable("finalAmount", finalAmount);
        context.setVariable("paymentMethod", paymentMethod);
        context.setVariable("orderNumber", orderNumber);
        String htmlContent = templateEngine.process("invoice", context);

        // 2. 将 HTML 转换为 PDF
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            ITextRenderer renderer = new ITextRenderer();

            // 注册字体
            renderer.getFontResolver().addFont("/pdf/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

            renderer.getSharedContext().setBaseURL("file:///C:/xiaoyh/invoice/"); // 设置静态资源路径
            renderer.setDocumentFromString(htmlContent);
            renderer.layout();
            renderer.createPDF(outputStream);
            return outputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("发票PDF生成失败", e);
            throw new BusinessException("发票PDF生成失败");
        }
    }

    public static void importPdf(String configPath, String templatePath, String outputPath, Map<String, Object> data) {
        TemplateHandler.Template.build()
                .setConfigPath(configPath)
                .setDataSource(
                        TemplateHandler.DataSource.Thymeleaf.build()
                                .setTemplatePath(templatePath)
                                .setTemplateData(data)
                )
                .transform(outputPath);
    }

    // 生成 PDF 字节数组
    public static byte[] generatePdfBytes(String configPath, String templatePath, Map<String, Object> data) throws IOException {
        File tempFile = File.createTempFile("pdf_temp_", ".pdf");
        try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) {
            TemplateHandler.Template.build()
                    .setConfigPath(configPath)
                    .setDataSource(
                            TemplateHandler.DataSource.Thymeleaf.build()
                                    .setTemplatePath(templatePath)
                                    .setTemplateData(data)
                    )
                    .transform(fileOutputStream); // 输出到文件流

            return Files.readAllBytes(tempFile.toPath()); // 读取文件字节并返回
        } catch (Exception e) {
            log.error("PDF生成失败", e);
            e.printStackTrace();
            throw new BusinessException("PDF生成失败");
        } finally {
            tempFile.delete(); // 删除临时文件
        }
    }


    public static Map<String, Object> convertToMap(Object obj) {
        Map<String, Object> map = new HashMap<>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                map.put(field.getName(), field.get(obj));
            } catch (IllegalAccessException e) {
                log.error("转换对象为Map失败", e);
                e.printStackTrace();
            }
        }
        return map;
    }


    public static void main(String[] args) throws IOException {

//        byte[] invoicePdf = generateInvoicePdf("test", "123456789",
//                "test@test.com", "test address", "test",
//                "test", goodsInvoices, "100", "10",
//                "0", "110", "支付宝", "1234567890");
//        try {
//            FileUtils.writeByteArrayToFile(new File("C:\\xiaoyh\\invoice\\test.pdf"), invoicePdf);
//            System.out.println("PDF 生成成功");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        // 创建商品项列表
        List<GoodsInvoiceItem> items = new ArrayList<>();

        // 商品1：无线鼠标
        items.add(new GoodsInvoiceItem(
                "无线鼠标",        // 商品名称
                "MX1001",         // 商品编号
                "个",             // 单位
                2,                // 数量
                "120",            // 单价（不含税）
                "240.00",            // 总金额（不含税）
                "10%",            // 税率
                "264.00"             // 含税金额（总价 + 税额）
        ));

        // 商品2：机械键盘
        items.add(new GoodsInvoiceItem(
                "机械键盘",        // 商品名称
                "KB2002",         // 商品编号
                "个",             // 单位
                1,                // 数量
                "450",            // 单价（不含税）
                "450.00",            // 总金额（不含税）
                "10%",            // 税率
                "495.00"             // 含税金额（总价 + 税额）
        ));

        // 商品3：显示器
        items.add(new GoodsInvoiceItem(
                "显示器",          // 商品名称
                "DS3003",         // 商品编号
                "台",             // 单位
                1,                // 数量
                "2200",           // 单价（不含税）
                "2200.00",           // 总金额（不含税）
                "13%",            // 税率
                "2496.00"            // 含税金额（总价 + 税额）
        ));

        // 创建发票对象并设置属性
        GoodsInvoice goodsInvoice = new GoodsInvoice();

        // 设置发票号
        goodsInvoice.setInvoiceNumber("A1234567890");

        // 设置开票单位
        goodsInvoice.setIssuer("南京市文达科技有限公司");

        // 设置发票项（商品列表）
        goodsInvoice.setItems(items);

        // 设置备注
        goodsInvoice.setRemarks("电子产品购买");

        // 设置买方信息
        goodsInvoice.setBuyerName("张三");
        goodsInvoice.setBuyerTaxCode("913201XX123456789");  // 假设的买方税号

        // 设置卖方信息
        goodsInvoice.setSellerName("南京市文达科技有限公司");
        goodsInvoice.setSellerTaxCode("913201XX987654321");  // 假设的卖方税号

        // 设置开票日期
        goodsInvoice.setIssueDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));

        // 设置开票人信息
        goodsInvoice.setIssuer("李四");

        // 计算合计金额、税额
        goodsInvoice.setTotalAmount("¥2890.00");
        goodsInvoice.setTotalTax("¥290.00");
        // 假设的价税合计（大写和小写）
        goodsInvoice.setTotalInWords("叁佰捌拾元整");
        goodsInvoice.setTotalInDigits("¥3180.00");

        // 转换成Map格式，以便模板处理
        Map<String, Object> data = convertToMap(goodsInvoice);

        // 定义文件路径和模板路径
        String configPath = "pdf/fop.xconf";
        String templatePath = "pdf/goodsInvoice.fo";
//        String outputPath = "C:\\xiaoyh\\invoice\\Thymeleaf_" + System.currentTimeMillis() + ".pdf";

        // 调用通用方法生成PDF
//        importPdf(configPath, templatePath, outputPath, data);
        byte[] bytes = generatePdfBytes(configPath, templatePath, data);
        try {
            FileUtils.writeByteArrayToFile(new File("C:\\xiaoyh\\invoice\\Thymeleaf_" + System.currentTimeMillis() + ".pdf"), bytes);
            System.out.println("PDF 生成成功");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
